package com.dbflow5.reactivestreams.structure;

import com.dbflow5.adapter.ModelAdapter;
import com.dbflow5.config.FlowManager;
import com.dbflow5.database.DatabaseWrapper;
import io.reactivex.rxjava3.core.Completable;
import io.reactivex.rxjava3.core.Single;

import java.util.Collection;

/**
 * Description: Wraps most [ModelAdapter] modification operations into RX-style constructs.
 */
public class RXModelAdapter<T> extends RXRetrievalAdapter<T> {
    private final ModelAdapter<T> modelAdapter;

    public RXModelAdapter(ModelAdapter<T> modelAdapter) {
        super(modelAdapter);
        this.modelAdapter = modelAdapter;
    }

    public RXModelAdapter(Class<T> table) {
        this(FlowManager.modelAdapter(table));
    }

    public Single<Boolean> save(T model, DatabaseWrapper databaseWrapper) {
        return Single.fromCallable(() -> modelAdapter.save(model, databaseWrapper));
    }

    public Completable saveAll(Collection<T> models, DatabaseWrapper databaseWrapper) {
        return Completable.fromCallable(() -> {
            modelAdapter.saveAll(models, databaseWrapper);
            return null;
        });
    }

    public Single<Long> insert(T model, DatabaseWrapper databaseWrapper) {
        return Single.fromCallable(() -> modelAdapter.insert(model, databaseWrapper));
    }

    public Completable insertAll(Collection<T> models, DatabaseWrapper databaseWrapper) {
        return Completable.fromCallable(() -> {
            modelAdapter.insertAll(models, databaseWrapper);
            return null;
        });
    }

    public Single<Boolean> update(T model, DatabaseWrapper databaseWrapper) {
        return Single.fromCallable(() -> modelAdapter.update(model, databaseWrapper));
    }

    public Completable updateAll(Collection<T> models, DatabaseWrapper databaseWrapper) {
        return Completable.fromCallable(() -> {
            modelAdapter.updateAll(models, databaseWrapper);
            return null;
        });
    }

    public Single<Boolean> delete(T model, DatabaseWrapper databaseWrapper) {
        return Single.fromCallable(() -> modelAdapter.delete(model, databaseWrapper));
    }

    public Completable deleteAll(Collection<T> models, DatabaseWrapper databaseWrapper) {
        return Completable.fromCallable(() -> {
            modelAdapter.deleteAll(models, databaseWrapper);
            return null;
        });
    }

    public static <T> RXModelAdapter<T> from(ModelAdapter<T> modelAdapter) {
        return new RXModelAdapter<>(modelAdapter);
    }

    public static <T> RXModelAdapter<T> from(Class<T> table) {
        return new RXModelAdapter<>(table);
    }
}
